package cn.tedu.submarine;

import javax.swing.*;
import java.awt.*;
import java.io.Serializable;
import java.util.Random;

/**
 * 本类为参与对象的超类，基于面向对象思想，封装了对象的共有属性和共有行为
 * @author XingHaiYang
 * @date 2022/8/27 15:16
 */
public abstract class SeaObject implements Serializable {
    /**
     * SeaObject中设计状态常量LIVE、DEAD，state变量表示当前状态,默认是LIVE活着的
     */
    public static final long serialVersionUID = 1L;
    public static final int LIVE = 0; //活着的
    public static final int DEAD = 1; //死了的
    protected int state = LIVE; //当前状态(默认为活着的)

    /**
     * 从参与的角色中抽取的共有属性
     */
    protected int width;
    protected int height;
    protected int x;
    protected int y;
    protected int speed;

    /**
     * 为战舰、炸弹、水雷设计的构造方法
     * @param width
     * @param height
     * @param x
     * @param y
     * @param speed
     */
    public SeaObject(int width, int height, int x, int y, int speed) {
        this.width = width;
        this.height = height;
        this.x = x;
        this.y = y;
        this.speed = speed;
    }

    /**
     * 为三种潜艇设计的构造方法
     * @param width
     * @param height
     */
    public SeaObject(int width, int height) {
        this.width = width;
        this.height = height;
        x = -width; //负的潜艇的宽
        Random rand = new Random(); //随机数对象
        y = rand.nextInt(World.HEIGHT-height-150+1)+150; //150到(窗口高-潜艇高)之内的随机数
        speed = rand.nextInt(3)+1; //1到3之内的随机数
    }

    /**
     * 设计获取图片的抽象方法getImage()
     */
    public abstract ImageIcon getImage();

    /**
     * 判断对象是否是活着的
     * @return 若当前状态为LIVE，表示为活着的，返回true，否则返回false
     */
    public boolean isLive(){
        return state==LIVE;
    }

    /**
     * 判断对象是否是死了的
     * @return 若当前状态为DEAD，表示为死了的，返回true，否则返回false
     */
    public boolean isDead(){
        return state==DEAD;
    }

    /**
     * 判断对象若活着，画对象
     * @param g 画笔
     */
    public void paintImage(Graphics g){
        if(this.isLive()){
            this.getImage().paintIcon(null,g,this.x,this.y);
        }
    }

    /**
     * 在超类中定义抽象的move()方法，因为每个对象的移动轨迹不一样，
     * 所以谁实现这个方法，可以定义自己的移动轨迹
     */
    public abstract void move();

    /**
     * 综合分析：潜艇、炸弹、水雷会越界，战舰不会越界，所以这里定义检测潜艇越界的方法，
     * 然后炸弹和水雷中可以重写超类中越界的方法
     */
    public boolean isOutOfBounds(){
        return x>=World.WIDTH; //潜艇的x>=窗口的宽，即为越界了
    }

    /**
     * 检测碰撞  this:一个对象
     * @param other 另一个对象
     * @return 是否撞上了，撞上返回true，否则返回false
     */
    public boolean isHit(SeaObject other){
        //假设:this表示潜艇，other表示炸弹
        int x1 = this.x-other.width;  //x1:潜艇的x-炸弹的宽
        int x2 = this.x+this.width;   //x2:潜艇的x+潜艇的宽
        int y1 = this.y-other.height; //y1:潜艇的y-炸弹的高
        int y2 = this.y+this.height;  //y2:潜艇的y+潜艇的高
        int x = other.x; //x:炸弹的x
        int y = other.y; //y:炸弹的y
        return x>=x1 && x<=x2
                &&
                y>=y1 && y<=y2; //x在x1与x2之间，并且，y在y1与y2之间，即为撞上了
    }

    /** 海洋对象去死 */
    public void goDead(){
        state = DEAD; //将当前状态修改为DEAD死了的
    }
}
